package cn.com.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;

import com.sdicons.json.mapper.JSONMapper;
import com.sdicons.json.mapper.MapperException;
import com.sdicons.json.model.JSONValue;

import net.sf.json.JSONObject;

public class JsonUtil {

	public static void printJson(HttpServletResponse response, String json) {
		try {
			response.setContentType("text/html;charset=utf-8");
			response.setHeader("Access-Control-Allow-Origin", "*");
			response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
			response.setHeader("Access-Control-Allow-Headers",
					"Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma,Last-Modified, Cache-Control, Expires, Content-Type,X-E4M-With");
			response.getWriter().print(json);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static Object json2bean(JSONObject jo, Class<?> entityClass, String prefix) {
		Object o = null;
		try {
			o = entityClass.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
			return o;
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			return o;
		}
		try {
			PropertyDescriptor[] props = Introspector.getBeanInfo(o.getClass(), Object.class).getPropertyDescriptors();
			for (int i = 0; i < props.length; i++) {
				String name = props[i].getName();
				String jsonKey = name;
				if (!Util.isNull(prefix)) {
					jsonKey = jsonKey + prefix;
				}
				if (jo.containsKey(jsonKey)) {
					Class<?> type = props[i].getPropertyType();
					if ((type.equals(Byte.TYPE)) || (type.equals(Byte.class))) {
						if (!Util.isNull(jo.getString(jsonKey))) {
							props[i].getWriteMethod().invoke(o, new Object[] { Byte.valueOf(jo.getString(jsonKey)) });
						}
					} else if ((type.equals(Short.TYPE)) || (type.equals(Short.class))) {
						if (!Util.isNull(jo.getString(jsonKey))) {
							props[i].getWriteMethod().invoke(o, new Object[] { Short.valueOf(jo.getString(jsonKey)) });
						}
					} else if ((type.equals(Integer.TYPE)) || (type.equals(Integer.class))) {
						if (!Util.isNull(jo.getString(jsonKey))) {
							props[i].getWriteMethod().invoke(o,
									new Object[] { Integer.valueOf(jo.getString(jsonKey)) });
						}
					} else if ((type.equals(Long.TYPE)) || (type.equals(Long.class))) {
						if (!Util.isNull(jo.getString(jsonKey))) {
							props[i].getWriteMethod().invoke(o, new Object[] { Long.valueOf(jo.getString(jsonKey)) });
						}
					} else if ((type.equals(Float.TYPE)) || (type.equals(Float.class))) {
						if (!Util.isNull(jo.getString(jsonKey))) {
							props[i].getWriteMethod().invoke(o, new Object[] { Float.valueOf(jo.getString(jsonKey)) });
						}
					} else if ((type.equals(Double.TYPE)) || (type.equals(Double.class))) {
						if (!Util.isNull(jo.getString(jsonKey))) {
							props[i].getWriteMethod().invoke(o, new Object[] { Double.valueOf(jo.getString(jsonKey)) });
						}
					} else if ((type.equals(Boolean.TYPE)) || (type.equals(Boolean.class))) {
						if (!Util.isNull(jo.getString(jsonKey))) {
							props[i].getWriteMethod().invoke(o,
									new Object[] { Boolean.valueOf(jo.getString(jsonKey)) });
						}
					} else if (type.equals(String.class)) {
						props[i].getWriteMethod().invoke(o, new Object[] { jo.getString(jsonKey) });
					} else if (type.equals(BigInteger.class)) {
						if (!Util.isNull(jo.getString(jsonKey))) {
							props[i].getWriteMethod().invoke(o, new Object[] {
									BigInteger.valueOf(Long.valueOf(jo.getString(jsonKey)).longValue()) });
						}
					} else if ((type.equals(BigDecimal.class)) && (!Util.isNull(jo.getString(jsonKey)))) {
						props[i].getWriteMethod().invoke(o,
								new Object[] { BigDecimal.valueOf(Long.valueOf(jo.getString(jsonKey)).longValue()) });
					}
				}
			}
		} catch (IntrospectionException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return o;
	}

	public static String object2json(Object o) {
		StringBuilder json = new StringBuilder();
		if (o == null) {
			json.append("\"\"");
		} else if ((o instanceof String)) {
			json.append("\"").append(string2json(o.toString())).append("\"");
		} else if (((o instanceof Byte)) || ((o instanceof Short)) || ((o instanceof Integer)) || ((o instanceof Long))
				|| ((o instanceof Float)) || ((o instanceof Double)) || ((o instanceof BigInteger))
//				|| ((o instanceof BigDecimal)) || ((o instanceof Boolean))) {
				|| ((o instanceof Boolean))) {
			json.append("\"").append(o.toString()).append("\"");
		}else if(o instanceof BigDecimal)
		{
			DecimalFormat myformat=new DecimalFormat("0.00");
			json.append("\"").append(myformat.format(o)).append("\"");
		}
		else if (((o instanceof byte[])) || ((o instanceof short[])) || ((o instanceof int[]))
				|| ((o instanceof long[])) || ((o instanceof float[])) || ((o instanceof double[]))
				|| ((o instanceof boolean[]))) {
			json.append(array2json(o));
		} else if ((o instanceof Object[])) {
			json.append(array2json((Object[]) o));
		} else if ((o instanceof Collection)) {
			json.append(collection2json((Collection) o));
		} else if ((o instanceof Map)) {
			json.append(map2json((Map) o));
		} else if ((o.getClass().getName().indexOf("java.") == 0) || (o.getClass().getName().indexOf("javax.") == 0)) {
			json.append("\"").append(string2json(o.toString())).append("\"");
		} else {
			json.append(bean2json(o));
		}
		return json.toString();
	}

	private static String bean2json(Object o) {
		StringBuilder json = new StringBuilder();
		json.append("{");
		try {
			PropertyDescriptor[] props = Introspector.getBeanInfo(o.getClass(), Object.class).getPropertyDescriptors();
			for (int i = 0; i < props.length; i++) {
				String name = props[i].getName();
				String value = object2json(props[i].getReadMethod().invoke(o, new Object[0]));
				json.append("\"").append(name).append("\"").append(":").append(value);
				if (i != props.length - 1) {
					json.append(",");
				}
			}
			json.append("}");
		} catch (IntrospectionException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return json.toString();
	}

	public static String string2json(String s) {
		if (s == null) {
			return "";
		}
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < s.length(); i++) {
			char ch = s.charAt(i);
			switch (ch) {
			case '\'':
				sb.append("\\'");
				break;
			case '"':
				sb.append("\\\"");
				break;
			case '\\':
				sb.append("\\\\");
				break;
			case '\b':
				sb.append("\\b");
				break;
			case '\f':
				sb.append("\\f");
				break;
			case '\n':
				sb.append("\\n");
				break;
			case '\r':
				sb.append("\\r");
				break;
			case '\t':
				sb.append("\\t");
				break;
			case '/':
				sb.append("\\/");
				break;
			default:
				if ((ch >= 0) && (ch <= '\037')) {
					String ss = Integer.toHexString(ch);
					sb.append("\\u");
					for (int k = 0; k < 4 - ss.length(); k++) {
						sb.append('0');
					}
					sb.append(ss.toUpperCase());
				} else {
					sb.append(ch);
				}
				break;
			}
		}
		return sb.toString();
	}

	private static String array2json(Object[] array) {
		StringBuilder json = new StringBuilder();
		json.append("[");
		if (array.length > 0) {
			Object[] arrayOfObject = array;
			int j = array.length;
			for (int i = 0; i < j; i++) {
				Object obj = arrayOfObject[i];
				json.append(object2json(obj));
				json.append(",");
			}
			json.setCharAt(json.length() - 1, ']');
		} else {
			json.append("]");
		}
		return json.toString();
	}

	private static String array2json(Object array) {
		StringBuilder json = new StringBuilder();
		json.append("[");
		if ((array instanceof byte[])) {
			byte[] data = (byte[]) array;
			for (int i = 0; i < data.length; i++) {
				json.append("\"").append(data[i]).append("\"");
				if (i != data.length - 1) {
					json.append(",");
				}
			}
		} else if ((array instanceof short[])) {
			short[] data = (short[]) array;
			for (int i = 0; i < data.length; i++) {
				json.append("\"").append(data[i]).append("\"");
				if (i != data.length - 1) {
					json.append(",");
				}
			}
		} else if ((array instanceof int[])) {
			int[] data = (int[]) array;
			for (int i = 0; i < data.length; i++) {
				json.append("\"").append(data[i]).append("\"");
				if (i != data.length - 1) {
					json.append(",");
				}
			}
		} else if ((array instanceof long[])) {
			long[] data = (long[]) array;
			for (int i = 0; i < data.length; i++) {
				json.append("\"").append(data[i]).append("\"");
				if (i != data.length - 1) {
					json.append(",");
				}
			}
		} else if ((array instanceof float[])) {
			float[] data = (float[]) array;
			for (int i = 0; i < data.length; i++) {
				json.append("\"").append(data[i]).append("\"");
				if (i != data.length - 1) {
					json.append(",");
				}
			}
		} else if ((array instanceof double[])) {
			double[] data = (double[]) array;
			for (int i = 0; i < data.length; i++) {
				json.append("\"").append(data[i]).append("\"");
				if (i != data.length - 1) {
					json.append(",");
				}
			}
		} else if ((array instanceof boolean[])) {
			boolean[] data = (boolean[]) array;
			for (int i = 0; i < data.length; i++) {
				json.append("\"").append(data[i]).append("\"");
				if (i != data.length - 1) {
					json.append(",");
				}
			}
		}
		json.append("]");
		return json.toString();
	}

	private static String collection2json(Collection<?> collection) {
		StringBuilder json = new StringBuilder();
		json.append("[");
		if (collection.size() > 0) {
			for (Object obj : collection) {
				json.append(object2json(obj));
				json.append(",");
			}
			json.setCharAt(json.length() - 1, ']');
		} else {
			json.append("]");
		}
		return json.toString();
	}

	private static String map2json(Map<?, ?> map) {
		StringBuilder json = new StringBuilder();
		json.append("{");
		if (map.size() > 0) {
			for (Object key : map.keySet()) {
				json.append(object2json(key));
				json.append(":");
				json.append(object2json(map.get(key)));
				json.append(",");
			}
			json.setCharAt(json.length() - 1, '}');
		} else {
			json.append("}");
		}
		return json.toString();
	}

	/**
	 * JAVA对象转换成JSON字符串
	 * 
	 * @param obj
	 * @return
	 * @throws MapperException
	 */
	public static String objectToJsonStr(Object obj) throws MapperException {
		JSONValue jsonValue = JSONMapper.toJSON(obj);
		String jsonStr = jsonValue.render(false);
		return jsonStr;
	}
}
